<template>
  <div class="admin-dashboard">
    <!-- 页面标题和刷新按钮 -->
    <div class="page-header">
      <div class="header-title">控制台</div>
      <el-button type="primary" size="small" @click="refreshStats">
        <el-icon><Refresh /></el-icon>
        刷新数据
      </el-button>
    </div>

    <!-- 加载错误提示 -->
    <el-alert
      v-if="loadingError"
      title="数据加载失败，请刷新页面重试"
      type="error"
      closable
      show-icon
      style="margin-bottom: 20px"
    />

    <el-row :gutter="20">
      <!-- 统计卡片 -->
      <el-col :xs="24" :sm="12" :md="6" v-for="stat in statsData" :key="stat.title">
        <el-card class="stat-card" :body-style="{ padding: '20px' }">
          <div class="stat-header">
            <h3>{{ stat.title }}</h3>
            <el-icon class="stat-icon" :style="{ color: stat.color }">
              <component :is="stat.icon" />
            </el-icon>
          </div>
          <div class="stat-value">{{ stat.value }}</div>
          <div class="stat-meta">
            <span :class="stat.isUp ? 'up' : 'down'">
              <el-icon><component :is="stat.isUp ? 'ArrowUp' : 'ArrowDown'" /></el-icon>
              {{ stat.change }}%
            </span>
            <span class="period">今日新增</span>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="20" class="chart-row">
      <!-- 访问趋势 -->
      <el-col :xs="24" :md="16">
        <el-card class="chart-card">
          <template #header>
            <div class="card-header">
              <h3>访问趋势</h3>
              <el-radio-group v-model="visitPeriod" size="small" @change="handlePeriodChange">
                <el-radio-button value="week">周</el-radio-button>
                <el-radio-button value="month">月</el-radio-button>
                <el-radio-button value="year">年</el-radio-button>
              </el-radio-group>
            </div>
          </template>
          <div class="chart-container">
            <canvas ref="trendChartCanvas" class="trend-chart-canvas" v-loading="trendLoading"></canvas>
            <div v-if="trendData.length === 0 && !trendLoading" class="no-data">暂无数据</div>
          </div>
        </el-card>
      </el-col>

      <!-- 设备分布 -->
      <el-col :xs="24" :md="8">
        <el-card class="chart-card">
          <template #header>
            <div class="card-header">
              <h3>设备分布</h3>
            </div>
          </template>
          <div class="chart-container" v-loading="deviceLoading">
            <canvas ref="deviceChartCanvas" class="device-chart-canvas" v-if="deviceData.length > 0"></canvas>
            <div v-if="deviceData.length === 0 && !deviceLoading" class="no-data">暂无数据</div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="20" class="table-row">
      <!-- 最新文章 -->
      <el-col :xs="24" :lg="12">
        <el-card class="table-card">
          <template #header>
            <div class="card-header">
              <h3>最新文章</h3>
              <el-button text @click="goToArticles">查看全部</el-button>
            </div>
          </template>
          <el-table :data="latestArticles" style="width: 100%" empty-text="暂无数据">
            <el-table-column prop="title" label="标题" show-overflow-tooltip/>
            <el-table-column prop="author" label="作者" width="100"/>
            <el-table-column prop="createTime" label="发布时间" width="150"/>
          </el-table>
        </el-card>
      </el-col>

      <!-- 最新用户 -->
      <el-col :xs="24" :lg="12">
        <el-card class="table-card">
          <template #header>
            <div class="card-header">
              <h3>新注册用户</h3>
              <el-button text @click="goToUsers">查看全部</el-button>
            </div>
          </template>
          <el-table :data="newUsers" style="width: 100%" empty-text="暂无数据">
            <el-table-column prop="username" label="用户名" show-overflow-tooltip/>
            <el-table-column prop="nickname" label="昵称" show-overflow-tooltip/>
            <el-table-column prop="createTime" label="注册时间" width="150"/>
          </el-table>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
/* eslint-disable */
import { ref, computed, onMounted, watch, onUnmounted, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'
import { ElMessage, ElLoading } from 'element-plus'
import { 
  User, 
  Document, 
  ChatDotRound, 
  View as ViewIcon,
  ArrowUp, 
  ArrowDown,
  DataAnalysis,
  PieChart,
  RefreshRight as Refresh
} from '@element-plus/icons-vue'
import api from '@/api/index'

export default {
  name: 'AdminDashboard',
  components: {
    User, 
    Document, 
    ChatDotRound, 
    ViewIcon,
    ArrowUp, 
    ArrowDown,
    DataAnalysis,
    PieChart,
    Refresh
  },
  setup() {
    const router = useRouter()
    const store = useStore()
    const visitPeriod = ref('week')
    
    // Canvas引用
    const trendChartCanvas = ref(null)
    const deviceChartCanvas = ref(null)
    
    // 统计数据
    const statsData = ref([
      {
        title: '用户总数',
        value: '0',
        icon: 'User',
        color: '#409EFF',
        change: '0',
        isUp: true
      },
      {
        title: '文章总数',
        value: '0',
        icon: 'Document',
        color: '#67C23A',
        change: '0',
        isUp: true
      },
      {
        title: '评论总数',
        value: '0',
        icon: 'ChatDotRound',
        color: '#E6A23C',
        change: '0',
        isUp: true
      },
      {
        title: '访问量',
        value: '0',
        icon: 'ViewIcon',
        color: '#F56C6C',
        change: '0',
        isUp: true
      }
    ])
    
    // 趋势数据和设备分布数据
    const trendData = ref([])
    const deviceData = ref([])
    const trendLoading = ref(false)
    const deviceLoading = ref(false)
    
    // 计算最大访问量，用于显示图表条形
    const maxTrendValue = computed(() => {
      if (!trendData.value || trendData.value.length === 0) return 100
      return Math.max(...trendData.value.map(item => item.value)) || 100
    })
    
    // 计算设备总数
    const totalDeviceValue = computed(() => {
      if (!deviceData.value || deviceData.value.length === 0) return 100
      return deviceData.value.reduce((sum, item) => sum + item.value, 0) || 100
    })
    
    // 获取颜色
    const colors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#909399']
    const getColor = (index) => {
      return colors[index % colors.length]
    }
    
    // 绘制趋势折线图
    const drawTrendChart = () => {
      const canvas = trendChartCanvas.value
      if (!canvas || !trendData.value || trendData.value.length === 0) return
      
      // 设置画布大小匹配容器（适应高DPI屏幕）
      const dpr = window.devicePixelRatio || 1
      const rect = canvas.getBoundingClientRect()
      canvas.width = rect.width * dpr
      canvas.height = rect.height * dpr
      
      const ctx = canvas.getContext('2d')
      ctx.scale(dpr, dpr)
      
      // 清除画布
      ctx.clearRect(0, 0, rect.width, rect.height)
      
      // 设置内边距
      const padding = { top: 30, right: 40, bottom: 50, left: 50 }
      const chartWidth = rect.width - padding.left - padding.right
      const chartHeight = rect.height - padding.top - padding.bottom
      
      // 计算Y轴刻度
      const maxValue = maxTrendValue.value
      const yAxisTicks = 5
      const yAxisStep = maxValue / yAxisTicks
      
      // 绘制背景网格
      ctx.beginPath()
      ctx.strokeStyle = '#eee'
      ctx.lineWidth = 1
      
      // 水平网格线
      for (let i = 0; i <= yAxisTicks; i++) {
        const y = padding.top + chartHeight - (i * chartHeight / yAxisTicks)
        ctx.moveTo(padding.left, y)
        ctx.lineTo(rect.width - padding.right, y)
        ctx.stroke()
        
        // 添加Y轴标签
        ctx.fillStyle = '#666'
        ctx.textAlign = 'right'
        ctx.textBaseline = 'middle'
        ctx.font = '12px Arial'
        ctx.fillText(Math.round(i * yAxisStep), padding.left - 10, y)
      }
      
      // 垂直网格线（每个数据点）
      const data = trendData.value
      for (let i = 0; i < data.length; i++) {
        const x = padding.left + (i * chartWidth / (data.length - 1))
        
        // 垂直网格线
        ctx.beginPath()
        ctx.moveTo(x, padding.top)
        ctx.lineTo(x, padding.top + chartHeight)
        ctx.strokeStyle = '#eee'
        ctx.stroke()
        
        // X轴标签
        ctx.fillStyle = '#666'
        ctx.textAlign = 'center'
        ctx.textBaseline = 'top'
        ctx.font = '12px Arial'
        
        // 根据数据点数量调整标签显示
        let shouldShowLabel = false;
        if (data.length <= 7) {
          // 少于7个数据点时显示所有标签
          shouldShowLabel = true;
        } else if (data.length <= 12) {
          // 7-12个数据点时，显示首尾和每隔一个点的标签
          shouldShowLabel = (i === 0 || i === data.length - 1 || i % 2 === 0);
        } else {
          // 更多数据点时，显示首尾和均匀分布的几个标签
          const step = Math.max(2, Math.floor(data.length / 6));
          shouldShowLabel = (i === 0 || i === data.length - 1 || i % step === 0);
        }
        
        // 只绘制应该显示的标签
        if (shouldShowLabel) {
          // 格式化日期确保简洁清晰
          let label = data[i].date;
          
          // 根据当前周期格式化日期
          if (visitPeriod.value === 'year') {
            // 年视图中，根据位置决定是否显示年份
            try {
              const dateParts = label.split('-');
              if (dateParts.length >= 2) {
                const year = dateParts[0];
                const month = parseInt(dateParts[1]);
                
                // 如果是第一个月或特定的月份(如1月)显示年份和月份，其他只显示月份
                if (i === 0 || month === 1 || month % 6 === 0) {
                  label = `${year}年${month}月`;
                } else {
                  label = `${month}月`;
                }
              }
            } catch (e) {
              console.error('日期格式化错误:', e);
            }
          } else if (visitPeriod.value === 'month' && data.length > 15) {
            // 月视图且数据点较多时，只显示日期部分
            try {
              const dateParts = label.split('-');
              if (dateParts.length >= 3) {
                label = dateParts[2];
              }
            } catch (e) {
              console.error('日期格式化错误:', e);
            }
          }
          
          // 绘制X轴标签
          ctx.fillText(label, x, padding.top + chartHeight + 10);
        }
      }
      
      // 绘制X轴和Y轴
      ctx.beginPath()
      ctx.strokeStyle = '#ddd'
      ctx.lineWidth = 1
      // X轴
      ctx.moveTo(padding.left, padding.top + chartHeight)
      ctx.lineTo(rect.width - padding.right, padding.top + chartHeight)
      // Y轴
      ctx.moveTo(padding.left, padding.top)
      ctx.lineTo(padding.left, padding.top + chartHeight)
      ctx.stroke()
      
      // 准备折线数据点坐标
      const points = []
      for (let i = 0; i < data.length; i++) {
        const x = padding.left + (i * chartWidth / (data.length - 1))
        const y = padding.top + chartHeight - (data[i].value / maxValue * chartHeight)
        points.push({ x, y })
      }
      
      // 绘制折线
      if (points.length > 1) {
        // 绘制面积
        ctx.beginPath()
        ctx.moveTo(points[0].x, points[0].y)
        
        // 连接所有点
        for (let i = 1; i < points.length; i++) {
          ctx.lineTo(points[i].x, points[i].y)
        }
        
        // 添加闭合路径，用于面积填充
        ctx.lineTo(points[points.length - 1].x, padding.top + chartHeight)
        ctx.lineTo(points[0].x, padding.top + chartHeight)
        ctx.closePath()
        
        // 创建渐变填充
        const gradient = ctx.createLinearGradient(0, padding.top, 0, padding.top + chartHeight)
        gradient.addColorStop(0, 'rgba(64, 158, 255, 0.3)')
        gradient.addColorStop(1, 'rgba(64, 158, 255, 0.05)')
        ctx.fillStyle = gradient
        ctx.fill()
        
        // 重新绘制线条，使它在填充区域上方
        ctx.beginPath()
        ctx.moveTo(points[0].x, points[0].y)
        
        for (let i = 1; i < points.length; i++) {
          ctx.lineTo(points[i].x, points[i].y)
        }
        
        ctx.strokeStyle = '#409EFF'
        ctx.lineWidth = 2
        ctx.stroke()
      }
      
      // 绘制数据点
      for (let i = 0; i < points.length; i++) {
        const x = points[i].x
        const y = points[i].y
        
        ctx.beginPath()
        ctx.arc(x, y, 4, 0, Math.PI * 2)
        ctx.fillStyle = '#fff'
        ctx.fill()
        ctx.strokeStyle = '#409EFF'
        ctx.lineWidth = 2
        ctx.stroke()
        
        // 显示数据值
        ctx.fillStyle = '#409EFF'
        ctx.textAlign = 'center'
        ctx.textBaseline = 'bottom'
        ctx.font = 'bold 12px Arial'
        ctx.fillText(data[i].value, x, y - 10)
      }
    }
    
    // 绘制设备分布饼图
    const drawDeviceChart = () => {
      const canvas = deviceChartCanvas.value
      if (!canvas || !deviceData.value || deviceData.value.length === 0) return
      
      // 设置画布大小匹配容器（适应高DPI屏幕）
      const dpr = window.devicePixelRatio || 1
      const rect = canvas.getBoundingClientRect()
      canvas.width = rect.width * dpr
      canvas.height = rect.height * dpr
      
      const ctx = canvas.getContext('2d')
      ctx.scale(dpr, dpr)
      
      // 清除画布
      ctx.clearRect(0, 0, rect.width, rect.height)
      
      // 计算饼图中心和半径
      const centerX = rect.width / 2
      const centerY = rect.height / 2 - 20  // 稍微上移，给下方的图例留出更多空间
      const radius = Math.min(centerX, centerY) * 0.6  // 减小饼图尺寸
      
      // 开始绘制饼图
      let startAngle = 0
      let total = totalDeviceValue.value
      
      // 饼图数据
      deviceData.value.forEach((item, index) => {
        // 计算当前扇区角度
        const sliceAngle = (item.value / total) * 2 * Math.PI
        
        // 绘制扇区
        ctx.beginPath()
        ctx.moveTo(centerX, centerY)
        ctx.arc(centerX, centerY, radius, startAngle, startAngle + sliceAngle)
        ctx.closePath()
        
        // 使用映射的颜色
        ctx.fillStyle = getColor(index)
        ctx.fill()
        
        // 计算标签位置 - 移到扇区外部
        const labelAngle = startAngle + sliceAngle / 2
        const percentage = Math.round((item.value / total) * 100)
        
        // 所有扇区都显示标签，但根据大小调整显示位置和方式
        const labelRadius = percentage >= 5 ? radius * 1.15 : radius * 1.3
        const labelX = centerX + Math.cos(labelAngle) * labelRadius
        const labelY = centerY + Math.sin(labelAngle) * labelRadius
        
        // 绘制百分比标签
        ctx.fillStyle = '#303133'
        ctx.font = 'bold 14px Arial'
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'
        ctx.fillText(`${percentage}%`, labelX, labelY)
        
        // 特别小的扇区（如3%）添加指示线，更清晰地指向对应扇区
        if (percentage < 5) {
          // 绘制连接线
          const innerX = centerX + Math.cos(labelAngle) * radius
          const innerY = centerY + Math.sin(labelAngle) * radius
          
          ctx.beginPath()
          ctx.moveTo(innerX, innerY)
          ctx.lineTo(labelX, labelY)
          ctx.strokeStyle = '#909399'
          ctx.lineWidth = 1
          ctx.stroke()
        }
        
        // 更新下一个扇区的起始角度
        startAngle += sliceAngle
      })
      
      // 绘制图例 - 放在饼图下方
      const legendItemHeight = 25
      const legendStartY = centerY + radius + 30  // 确保图例在饼图下方足够距离
      
      // 居中显示图例
      const legendWidth = rect.width - 40  // 图例宽度
      const legendStartX = (rect.width - legendWidth) / 2  // 居中
      
      deviceData.value.forEach((item, index) => {
        const row = Math.floor(index / 2)  // 每行放两个图例项
        const col = index % 2
        
        const legendX = legendStartX + col * (legendWidth / 2)
        const legendY = legendStartY + row * legendItemHeight
        
        // 绘制图例颜色块
        ctx.fillStyle = getColor(index)
        ctx.fillRect(legendX, legendY, 12, 12)
        
        // 绘制图例文字
        ctx.fillStyle = '#606266'
        ctx.font = '12px Arial'
        ctx.textAlign = 'left'
        ctx.textBaseline = 'middle'
        
        // 限制文本长度，防止溢出
        const maxTextWidth = (legendWidth / 2) - 30
        let text = `${item.name}: ${item.value} (${Math.round((item.value / total) * 100)}%)`
        
        ctx.fillText(text, legendX + 18, legendY + 6, maxTextWidth)
      })
    }
    
    // 窗口大小变化时重绘图表
    const handleResize = () => {
      drawTrendChart()
      drawDeviceChart()
    }
    
    // 监听趋势数据变化，重绘图表
    watch(() => trendData.value, () => {
      drawTrendChart()
    })
    
    // 监听设备数据变化，重绘图表
    watch(() => deviceData.value, () => {
      // 使用nextTick确保DOM更新后再绘制
      nextTick(() => {
        drawDeviceChart()
      })
    })
    
    // 最新文章数据
    const latestArticles = ref([])
    
    // 最新用户数据
    const newUsers = ref([])
    
    // 加载错误状态
    const loadingError = ref(false)
    
    // 加载统计数据
    const fetchDashboardData = async () => {
      const loading = ElLoading.service({
        lock: true,
        text: '加载数据中...',
        background: 'rgba(255, 255, 255, 0.7)'
      })
      
      try {
        // 调用后端API获取仪表盘数据
        const response = await api.stat.getDashboardData()
        
        if (response && response.code === 0 && response.data) {
          console.log('获取到仪表盘数据:', response.data)
          const data = response.data
          
          // 更新统计卡片数据 - 计算今日新增百分比
          statsData.value[0].value = data.totalUsers || '0'
          const userPercent = data.totalUsers > 0 ? ((data.todayNewUsers / data.totalUsers) * 100).toFixed(1) : '0'
          statsData.value[0].change = userPercent
          statsData.value[0].isUp = (data.todayNewUsers > 0)
          
          statsData.value[1].value = data.totalArticles || '0'
          const articlePercent = data.totalArticles > 0 ? ((data.todayNewArticles / data.totalArticles) * 100).toFixed(1) : '0'
          statsData.value[1].change = articlePercent
          statsData.value[1].isUp = (data.todayNewArticles > 0)
          
          statsData.value[2].value = data.totalComments || '0'
          const commentPercent = data.totalComments > 0 ? ((data.todayNewComments / data.totalComments) * 100).toFixed(1) : '0'
          statsData.value[2].change = commentPercent
          statsData.value[2].isUp = (data.todayNewComments > 0)
          
          statsData.value[3].value = data.totalVisits || '0'
          // 更新访问量增长率
          statsData.value[3].change = '0'
          statsData.value[3].isUp = true
        } else {
          console.error('获取仪表盘数据失败:', response)
          loadingError.value = true
          ElMessage.error('获取统计数据失败: ' + (response?.message || '未知错误'))
        }
      } catch (error) {
        console.error('获取仪表盘数据出错:', error)
        loadingError.value = true
        ElMessage.error('获取统计数据出错: ' + error.message)
      } finally {
        loading.close()
      }
    }
    
    // 获取最新文章
    const fetchLatestArticles = async () => {
      try {
        // 调用获取最新文章的API，限制5条
        const response = await api.article.getList({ 
          page: 1,
          size: 5,
          sort: 'createTime',
          order: 'desc'
        })
        
        if (response && response.code === 0) {
          console.log('获取到最新文章数据:', response)
          
          // 处理不同的数据格式
          let articleData = [];
          
          if (!response.data) {
            console.warn('没有收到文章数据')
            return
          }
          
          // 检查response.data的类型和结构
          if (Array.isArray(response.data)) {
            // 如果直接是数组格式
            articleData = response.data
          } else if (typeof response.data === 'object') {
            // 如果是对象格式
            if (response.data.list && Array.isArray(response.data.list)) {
              // 标准分页格式 {list: [...], total: n}
              articleData = response.data.list
            } else {
              // 尝试将对象转换为数组（如果是键值对形式）
              const possibleArray = Object.values(response.data).filter(item => 
                item && typeof item === 'object' && item.id && item.title
              )
              
              if (possibleArray.length > 0) {
                articleData = possibleArray
              } else {
                console.warn('无法从响应中提取文章数据:', response.data)
                latestArticles.value = []
                return
              }
            }
          } else {
            console.warn('未知的数据格式:', typeof response.data)
            latestArticles.value = []
            return
          }
          
          // 确保articleData是有效的数组
          if (!Array.isArray(articleData) || articleData.length === 0) {
            console.warn('没有可用的文章数据')
            latestArticles.value = []
            return
          }
          
          // 格式化文章数据
          latestArticles.value = articleData.map(article => ({
            id: article.id,
            title: article.title,
            author: article.user?.nickname || article.user?.username || article.userName || article.author || '未知作者',
            createTime: formatDate(article.createTime)
          }))
          
          console.log('处理后的文章数据:', latestArticles.value)
        } else {
          console.error('获取最新文章失败:', response)
          ElMessage.warning('获取最新文章失败')
          latestArticles.value = []
        }
      } catch (error) {
        console.error('获取最新文章出错:', error)
        ElMessage.warning('获取最新文章出错')
        latestArticles.value = []
      }
    }
    
    // 获取最新用户
    const fetchNewUsers = async () => {
      try {
        // 添加加载状态
        const loadingInstance = ElLoading.service({
          target: '.admin-dashboard .table-row .table-card:last-child',
          text: '加载用户数据...',
          background: 'rgba(255, 255, 255, 0.7)'
        });
        
        // 调用获取最新用户的API，限制5条
        const response = await api.admin.getUserList({
          page: 1,
          size: 5,
          sort: 'createTime',
          order: 'desc'
        });
        
        console.log('获取到的用户API完整响应:', response);
        loadingInstance.close();
        
        // 处理响应数据
        processUserResponse(response);
      } catch (error) {
        console.error('获取最新用户出错:', error);
        ElMessage.warning('获取最新用户出错: ' + (error.message || '未知错误'));
        newUsers.value = [];
      }
    };
    
    // 处理用户API响应
    const processUserResponse = (response) => {
      if (!response) {
        console.error('获取最新用户失败: 响应为空');
        ElMessage.warning('获取最新用户失败: 服务器未返回数据');
        newUsers.value = [];
        return;
      }
      
      if (response.code !== 0) {
        console.error('获取最新用户失败:', response.message || '未知错误');
        ElMessage.warning('获取最新用户失败: ' + (response.message || '未知错误'));
        newUsers.value = [];
        return;
      }
      
      if (!response.data) {
        console.warn('用户数据为空');
        newUsers.value = [];
        return;
      }
      
      // 提取用户数据数组
      let userData = extractUserDataArray(response.data);
      
      // 如果提取失败，显示错误
      if (!userData || userData.length === 0) {
        console.warn('没有可用的用户数据');
        newUsers.value = [];
        return;
      }
      
      // 格式化用户数据
      newUsers.value = userData.map(user => ({
        id: user.id,
        username: user.username || '未知用户名',
        nickname: user.nickname || user.username || '未知昵称',
        createTime: formatDate(user.createTime)
      }));
      
      console.log('处理后的用户数据:', newUsers.value);
    };
    
    // 从响应中提取用户数组
    const extractUserDataArray = (data) => {
      console.log('尝试从响应数据中提取用户列表:', data);
      
      // 如果直接是数组
      if (Array.isArray(data)) {
        console.log('数据本身是数组格式');
        return data;
      }
      
      // 如果是分页对象格式
      if (data.list && Array.isArray(data.list)) {
        console.log('数据是标准分页格式，包含list数组，条数:', data.list.length);
        return data.list;
      }
      
      // 尝试将对象内的所有属性转换为数组
      try {
        const possibleArray = Object.values(data).filter(item => 
          item && typeof item === 'object' && item.id !== undefined
        );
        
        if (possibleArray.length > 0) {
          console.log('从对象中提取到数组数据:', possibleArray.length, '条');
          return possibleArray;
        }
      } catch (error) {
        console.error('从对象提取数组失败:', error);
      }
      
      // 未能提取到有效数据
      console.error('无法从响应中提取用户数据');
      return [];
    };
    
    // 格式化日期
    const formatDate = (dateString) => {
      if (!dateString) return '未知时间'
      
      try {
        const date = new Date(dateString)
        return date.toLocaleString('zh-CN', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit'
        })
      } catch (error) {
        console.error('日期格式化错误:', error)
        return dateString || '未知时间'
      }
    }
    
    // 跳转到文章管理
    const goToArticles = () => {
      router.push('/admin/articles')
    }
    
    // 跳转到用户管理
    const goToUsers = () => {
      router.push('/admin/users')
    }
    
    // 加载趋势图数据
    const loadTrendData = async () => {
      trendLoading.value = true
      try {
        console.log('正在加载访问趋势数据, period =', visitPeriod.value)
        const response = await api.stat.getVisitTrend(visitPeriod.value)
        
        if (response && response.code === 0 && response.data) {
          console.log('获取到趋势数据:', response.data)
          trendData.value = response.data
        } else {
          console.error('获取趋势数据失败:', response)
          ElMessage.warning('获取趋势数据失败')
        }
      } catch (error) {
        console.error('获取趋势数据出错:', error)
        ElMessage.warning('获取趋势数据出错，请稍后重试')
      } finally {
        trendLoading.value = false
      }
    }
    
    // 加载设备分布数据
    const loadDeviceDistribution = async () => {
      deviceLoading.value = true
      try {
        console.log('正在加载设备分布数据')
        const response = await api.stat.getDeviceDistribution()
        
        if (response && response.code === 0 && response.data) {
          console.log('获取到设备分布数据:', response.data)
          deviceData.value = response.data
          
          // 确保在数据更新后、DOM更新后再绘制图表
          nextTick(() => {
            drawDeviceChart()
          })
        } else {
          console.error('获取设备分布数据失败:', response)
          ElMessage.warning('获取设备分布数据失败')
        }
      } catch (error) {
        console.error('获取设备分布数据出错:', error)
        ElMessage.warning('获取设备分布数据出错，请稍后重试')
      } finally {
        deviceLoading.value = false
      }
    }
    
    // 监听时间范围变化
    const handlePeriodChange = () => {
      console.log('时间范围变化为:', visitPeriod.value)
      loadTrendData()
    }
    
    // 刷新统计数据
    const refreshStats = () => {
      fetchDashboardData()
      fetchLatestArticles()
      fetchNewUsers()
      loadTrendData()
      loadDeviceDistribution()
    }
    
    onMounted(() => {
      console.log('AdminDashboard组件挂载')
      // 初始加载数据
      fetchDashboardData()
      fetchLatestArticles()
      fetchNewUsers()
      loadTrendData()
      loadDeviceDistribution()
      
      // 添加窗口大小变化监听
      window.addEventListener('resize', handleResize)
      
      // 确保Canvas元素已挂载后再绘制图表
      nextTick(() => {
        drawTrendChart()
        drawDeviceChart()
      })
    })
    
    onUnmounted(() => {
      // 移除窗口大小变化监听
      window.removeEventListener('resize', handleResize)
    })
    
    return {
      visitPeriod,
      statsData,
      latestArticles,
      newUsers,
      loadingError,
      trendData,
      deviceData,
      trendLoading,
      deviceLoading,
      trendChartCanvas,
      deviceChartCanvas,
      maxTrendValue,
      totalDeviceValue,
      getColor,
      goToArticles,
      goToUsers,
      handlePeriodChange,
      refreshStats
    }
  }
}
</script>

<style scoped>
.admin-dashboard {
  padding: 20px;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.header-title {
  font-size: 20px;
  font-weight: bold;
  color: #303133;
}

.stat-card {
  margin-bottom: 20px;
}

.stat-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.stat-header h3 {
  margin: 0;
  font-size: 16px;
  color: #606266;
}

.stat-icon {
  font-size: 24px;
}

.stat-value {
  font-size: 28px;
  font-weight: bold;
  margin-bottom: 10px;
}

.stat-meta {
  font-size: 14px;
  color: #909399;
}

.up {
  color: #67C23A;
}

.down {
  color: #F56C6C;
}

.period {
  margin-left: 10px;
}

.chart-row, .table-row {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header h3 {
  margin: 0;
  font-size: 16px;
  color: #303133;
}

.chart-container {
  height: 300px;
  width: 100%;
  position: relative;
  overflow: hidden;
}

.table-card {
  margin-bottom: 20px;
}

/* 访问趋势折线图样式 */
.trend-chart-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

.no-data {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 16px;
  color: #909399;
  background-color: rgba(255, 255, 255, 0.8);
}

/* 设备分布样式 */
.device-chart-canvas {
  width: 100%;
  height: 100%;
  display: block;
}
</style> 